package com.custom.customsweather

import android.content.Context
import android.graphics.*
import android.os.Handler
import android.os.Message
import android.util.AttributeSet
import android.util.Log
import android.view.MotionEvent
import android.view.View
import java.util.*

/**
 * @description：TODO
 * @Author MRyan
 * @Date 2020/3/1 16:49
 * @Version 1.0
 */
class CustomMoveClockView : View {
    private var mClockViewSize: Int = 0 //画布大小 = 0
    private var mClockSize: Int = 0  //控件大小 = 0
    private var mClockColor: Int = 0  //时钟外框颜色 = 0
    private var mCustomPanColor: Int = 0  //刻度线颜色 = 0
    private var mClockWidth: Int = 0  //时钟外框宽度 = 0
    private var mClockPaint //绘制整体轮廓画笔
            : Paint? = null
    private var mirclePanPaint //绘制刻度线
            : Paint? = null
    private var mircleCirPaint //绘制表芯
            : Paint? = null
    private var mirclePanTextPaint //时钟文字画笔
            : Paint? = null
    private var mCustomPanTextColor: Int = 0  //时钟文字颜色 = 0
    private var mCustomPanTextSize: Int = 0//时钟文字大小 = 0
    private var mClockHourPaint //绘制时钟
            : Paint? = null
    private var mClockMinutePaint //绘制分钟
            : Paint? = null
    private var mClockSecondPaint //绘制秒钟
            : Paint? = null
    private var mCalendar //获取时间
            : Calendar? = null
    private var mRadius = 0
    private var mClockRect //时钟轮廓位置
            : RectF? = null
    private var startY = 0
    private var startX = 0

    var centerX: Float = 0f
    var centerY: Float = 0f

    // 内圆半径
    var innerRadius = dpx2(83)

    // 外圆半径
    var outRadius = dpx2(90)

    // 阴影半径
    val shadowRadius = dp2px(20f)
    val shadowRadius2 = dp2px(35f)

    private val outPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        color = Color.parseColor("#e6e8db")
        maskFilter = BlurMaskFilter(shadowRadius2.toFloat(), BlurMaskFilter.Blur.SOLID)
    }

    // 内圆paint
    private val innerCirclePaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        shader = LinearGradient(
            centerX - innerRadius, centerY + innerRadius, centerX, centerY - innerRadius,
            Color.parseColor("#e0e2e5"), Color.parseColor("#758595"), Shader.TileMode.CLAMP
        )
    }

    constructor(context: Context?) : super(context) {}
    constructor(
        context: Context,
        attrs: AttributeSet?
    ) : super(context, attrs) {
        initAttrs(context, attrs) //自定义属性

        //发送消息，监测秒针
        mhandler.sendEmptyMessage(istrue)
    }

    constructor(
        context: Context?,
        attrs: AttributeSet?,
        defStyleAttr: Int
    ) : super(context, attrs, 0) {
    }

    init {
        // 禁用硬件加速
        setLayerType(LAYER_TYPE_SOFTWARE, null)
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        initPaint()
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        setMeasuredDimension(mClockViewSize, mClockViewSize)
        centerX = (mClockSize / 2).toFloat()
        centerY = (mClockSize / 2).toFloat()
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        //绘制刻度线 和 数字
        drwaGraduationLine(canvas)
        //绘制表针
        drawClockLine(canvas)
    }

    /***
     * 绘制表针
     * @param canvas
     */
    private fun drawClockLine(canvas: Canvas) {
        canvas.drawCircle(centerX, centerY, outRadius.toFloat(), outPaint)
        canvas.drawCircle(centerX, centerY, innerRadius.toFloat(), innerCirclePaint)
        canvas.save()
        //获取系统当时的时间
        var hour = mCalendar!![Calendar.HOUR]
        val minute = mCalendar!![Calendar.MINUTE]
        val second = mCalendar!![Calendar.SECOND]
        if (hour > 12) { //12小时质
            hour = hour - 12
        }
        val hourDregrees =
            hour / 12f * 360 + minute / 60f * 30 + 180 //时针旋转的角度 因为从12开始 所以需要旋转从180度开始
        val minuDegrees = minute / 60f * 360 + 180 //分针旋转的角度
        val sencondDegree = second / 60f * 360 + 180 //秒针旋转的角度
        Log.e(
            "MessageDreGrees",
            "$hourDregrees  $minuDegrees  $sencondDegree"
        )
        Log.e("MessageDreGree", "$hour  $minute  $second")
        canvas.rotate(hourDregrees, mClockSize / 2.toFloat(), mClockSize / 2.toFloat())
        canvas.drawLine(
            mClockSize / 2.toFloat(),
            mClockSize / 2 - 50.toFloat(),
            mClockSize / 2.toFloat(),
            mClockSize / 2 + 180.toFloat(),
            mClockHourPaint!!
        ) //画时针刻度线
        canvas.restore() //合并画布


        //绘制分针
        canvas.save()
        canvas.rotate(minuDegrees, mClockSize / 2.toFloat(), mClockSize / 2.toFloat()) //旋转画布
        canvas.drawLine(
            mClockSize / 2.toFloat(),
            mClockSize / 2 - 50.toFloat(),
            mClockSize / 2.toFloat(),
            mClockSize / 2 + 230.toFloat(),
            mClockMinutePaint!!
        ) //画时间刻度线;
        canvas.restore() //合并画布


        //绘制秒针
        canvas.save()
        canvas.rotate(sencondDegree, mClockSize / 2.toFloat(), mClockSize / 2.toFloat()) //旋转画布
        canvas.drawLine(
            mClockSize / 2.toFloat(),
            mClockSize / 2 - 50.toFloat(),
            mClockSize / 2.toFloat(),
            mClockSize / 2 + 300.toFloat(),
            mClockSecondPaint!!
        ) //画时间刻度线;
        canvas.restore() //合并画布
        canvas.save()
        //绘制表芯
        canvas.drawCircle(mClockSize / 2.toFloat(), mClockSize / 2.toFloat(), 15f, mircleCirPaint!!)
        canvas.restore()
    }

    /***
     * 绘制刻度线 和 数字
     * @param canvas
     */
    private fun drwaGraduationLine(canvas: Canvas) {
        //绘制 外轮廓的圆弧
        canvas.drawArc(mClockRect!!, 0f, 360f, false, mClockPaint!!)
        //绘制 刻度线和数字  （一圈360度 90度 180度 270度 360度为粗长 特定刻度 其余为小刻度）
        for (i in 0..59) {
            if (i == 0 || i == 15 || i == 30 || i == 45) {
                //画刻度线
                mirclePanPaint!!.strokeWidth = 15f
                mirclePanPaint!!.color = Color.parseColor("#FA838383")
                canvas.drawLine(
                    mClockSize / 2.toFloat(),
                    mClockWidth + 5.toFloat(),
                    mClockSize / 2.toFloat(),
                    mClockWidth + 50.toFloat(),
                    mirclePanPaint!!
                )
                //设置时间数字
                var degree = (i / 5).toString()
                if (i == 0) {
                    degree = "12"
                }
                //获取数字绘制位置
                val rect = Rect()
                mirclePanTextPaint!!.getTextBounds(degree, 0, degree.length, rect)
                mirclePanTextPaint!!.textSize = mCustomPanTextSize.toFloat()
                mirclePanTextPaint!!.strokeWidth = 8f
                mirclePanTextPaint!!.isFakeBoldText = true //设置数字粗体
                val dx = mClockSize / 2 - rect.width() / 2 - 18
                //绘制时间数字
                canvas.drawText(
                    degree,
                    dx.toFloat(),
                    mClockWidth + 120.toFloat(),
                    mirclePanTextPaint!!
                )
            } else if (i % 5 == 0) {
                mirclePanPaint!!.strokeWidth = 15f
                mirclePanPaint!!.color = mClockColor
                canvas.drawLine(
                    mClockSize / 2.toFloat(),
                    mClockWidth + 5.toFloat(),
                    mClockSize / 2.toFloat(),
                    mClockWidth + 40.toFloat(),
                    mirclePanPaint!!
                )
                //设置时间数字
                val degree = (i / 5).toString()
                //获取文字绘制位置
                val rect = Rect()
                mirclePanTextPaint!!.getTextBounds(degree, 0, degree.length, rect)
                mirclePanTextPaint!!.textSize = (mCustomPanTextSize * 0.6).toFloat()
                mirclePanTextPaint!!.strokeWidth = 8f
                val dx = mClockSize / 2 - rect.width() / 2
                //绘制时间数字
                canvas.drawText(
                    degree,
                    dx.toFloat(),
                    mClockWidth + 100.toFloat(),
                    mirclePanTextPaint!!
                )
            } else {
                mirclePanPaint!!.strokeWidth = 5f
                mirclePanPaint!!.color = mClockColor
                canvas.drawLine(
                    mClockSize / 2.toFloat(),
                    mClockWidth + 5.toFloat(),
                    mClockSize / 2.toFloat(),
                    mClockWidth + 30.toFloat(),
                    mirclePanPaint!!
                )
            }
            canvas.rotate(6f, mClockSize / 2.toFloat(), mClockSize / 2.toFloat())
        }
        //保存表盘和刻度的画布
        canvas.save()
    }

    /**
     * 获取自定义属性
     *
     * @param context
     * @param attrs
     */
    private fun initAttrs(
        context: Context,
        attrs: AttributeSet?
    ) {
        val typedArray =
            context.obtainStyledAttributes(attrs, R.styleable.CustomMoveClockView)
        mClockColor =
            typedArray.getColor(R.styleable.CustomMoveClockView_customClockColor, mClockColor)
        mCustomPanColor =
            typedArray.getColor(R.styleable.CustomMoveClockView_customPanColor, mCustomPanColor)
        mCustomPanTextColor = typedArray.getColor(
            R.styleable.CustomMoveClockView_customPanTextColor,
            mCustomPanTextColor
        )
        mCustomPanTextSize = typedArray.getDimension(
            R.styleable.CustomMoveClockView_customPanTextSize,
            dpx2(33).toFloat()
        ).toInt()
        mClockViewSize = typedArray.getDimension(
            R.styleable.CustomMoveClockView_customClockSize,
            dpx2(300).toFloat()
        ).toInt()
        mClockWidth = typedArray.getDimension(
            R.styleable.CustomMoveClockView_customClockborderWidth,
            dpx2(8).toFloat()
        ).toInt()
        typedArray.recycle()
        mClockSize = mClockViewSize //容错
        mRadius = mClockSize / 2
        mCalendar = Calendar.getInstance()
    }

    //消息队列机制
    private val mhandler: Handler = object : Handler() {
        override fun handleMessage(msg: Message) {
            when (msg.what) {
                istrue -> {
                    //重新获取时间
                    mCalendar = Calendar.getInstance()
                    //重新绘制界面
                    invalidate() //告诉UI主线程重新绘制
                    //再次发送消息，递归调用，再次监测秒针
                    sendEmptyMessageDelayed(istrue, 1000)
                }
                else -> {
                }
            }
        }
    }

    /**
     * 初始化画笔
     */
    private fun initPaint() {
        mClockPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
            color = mClockColor
            isAntiAlias = true
            style = Paint.Style.STROKE
            strokeWidth = 25F
            maskFilter = BlurMaskFilter(shadowRadius.toFloat(), BlurMaskFilter.Blur.SOLID)
        }

        mircleCirPaint = Paint()
        mircleCirPaint!!.color = mClockColor
        mircleCirPaint!!.isAntiAlias = true
        mircleCirPaint!!.style = Paint.Style.FILL
        mircleCirPaint!!.strokeWidth = 5f
        mirclePanPaint = Paint()
        mirclePanPaint!!.color = mCustomPanColor
        mirclePanPaint!!.isAntiAlias = true
        mirclePanPaint!!.style = Paint.Style.FILL
        mirclePanTextPaint = Paint()
        mirclePanTextPaint!!.color = mCustomPanTextColor
        mirclePanTextPaint!!.style = Paint.Style.FILL
        mClockHourPaint = Paint()
        mClockHourPaint!!.color = Color.parseColor("#FA838383")
        mClockHourPaint!!.style = Paint.Style.FILL
        mClockHourPaint!!.strokeWidth = 25f
        mClockMinutePaint = Paint()
        mClockMinutePaint!!.color = Color.parseColor("#FA838383")
        mClockMinutePaint!!.style = Paint.Style.FILL
        mClockMinutePaint!!.strokeWidth = 17f
        mClockSecondPaint = Paint()
        mClockSecondPaint!!.color = mCustomPanColor
        mClockSecondPaint!!.style = Paint.Style.FILL
        mClockSecondPaint!!.strokeWidth = 10f
        mClockRect =
            RectF(
                mClockWidth.toFloat(),
                mClockWidth.toFloat(),
                (mClockSize - mClockWidth).toFloat(),
                (mClockSize - mClockWidth).toFloat()
            )
    }

    //重写滑动事件
    override fun onTouchEvent(event: MotionEvent): Boolean {
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                Log.e("打印操作：", "按下了")
                //获取当前按下的坐标
                startX = event.rawX.toInt()
                startY = event.rawY.toInt()
            }
            MotionEvent.ACTION_MOVE -> {
                //获取移动后的坐标
                if (onMoveListener != null) {
                    onMoveListener!!.onMove(true) //接口回调 移动中
                }
                val moveX = event.rawX.toInt()
                val moveY = event.rawY.toInt()
                //拿到手指移动距离的大小
                val move_bigX = moveX - startX
                val move_bigY = moveY - startY
                Log.e("打印操作：", "\nX移动了$move_bigX\nY移动了$move_bigY")
                //拿到当前控件未移动的坐标
                var left = left
                var top = top
                left += move_bigX
                top += move_bigY
                val right = left + width
                val bottom = top + height
                layout(left, top, right, bottom)
                startX = moveX
                startY = moveY
            }
            MotionEvent.ACTION_UP -> {
                Log.e("打印操作：", "抬起了")
                if (onMoveListener != null) {
                    onMoveListener!!.onMove(false) //接口回调 未移动
                }
            }
        }
        return true //此处一定要返回true，否则监听不生效
    }

    /***
     * 定义接口 暴露接口
     */
    private var onMoveListener: OnMoveListener? = null

    interface OnMoveListener {
        fun onMove(isMove: Boolean)
    }

    fun setOnMoveListener(onMoveListener: OnMoveListener?) {
        this.onMoveListener = onMoveListener
    }

    fun dpx2(Value: Int): Int {
        val scale = resources.displayMetrics.density
        return (Value * scale + 0.5f).toInt()
    }


    fun dp2px(dpValue: Float): Int {
        val scale = this.resources.displayMetrics.density
        return (dpValue * scale + 0.5f).toInt()
    }

    companion object {
        private const val istrue = 521
    }
}